#!/usr/bin/env python3
"""
Configuration 配置模型
管理 git_pull_all 工具的配置参数和验证
"""

import os
import fnmatch
from typing import List, Dict, Any, Optional


class Configuration:
    """配置管理类"""
    
    def __init__(self, 
                 root_directory: str, 
                 include_patterns: Optional[List[str]] = None,
                 exclude_patterns: Optional[List[str]] = None,
                 verbose: bool = False, 
                 dry_run: bool = False, 
                 timeout: int = 300, 
                 max_workers: int = 4):
        """
        初始化配置对象
        
        Args:
            root_directory: 根目录路径
            include_patterns: 包含模式列表
            exclude_patterns: 排除模式列表
            verbose: 是否启用详细输出
            dry_run: 是否启用预览模式
            timeout: 命令执行超时时间（秒）
            max_workers: 最大工作线程数
        """
        self.root_directory = root_directory
        self.include_patterns = include_patterns or []
        self.exclude_patterns = exclude_patterns or []
        self.verbose = verbose
        self.dry_run = dry_run
        self.timeout = timeout
        self.max_workers = max_workers
        self.is_valid = False
        self.error_message = ""
        
        # 验证配置
        self._validate()
    
    def _validate(self) -> None:
        """
        验证配置参数的有效性
        """
        try:
            # 验证根目录
            if not self.root_directory:
                self.error_message = "目录不能为空"
                return
            
            if not os.path.exists(self.root_directory):
                self.error_message = f"不存在的目录: {self.root_directory}"
                return
            
            if not os.path.isdir(self.root_directory):
                self.error_message = f"路径不是目录: {self.root_directory}"
                return
            
            # 验证超时时间
            if self.timeout <= 0:
                self.error_message = "超时时间必须大于0"
                return
            
            # 验证工作线程数
            if self.max_workers <= 0:
                self.error_message = "工作线程数必须大于0"
                return
            
            # 验证模式
            for pattern in self.include_patterns + self.exclude_patterns:
                if not isinstance(pattern, str):
                    self.error_message = "模式必须是字符串"
                    return
            
            self.is_valid = True
            self.error_message = ""
            
        except Exception as e:
            self.error_message = f"配置验证失败: {str(e)}"
            self.is_valid = False
    
    def should_include_repository(self, repo_path: str) -> bool:
        """
        检查仓库是否应该被包含
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该包含
        """
        if not self.include_patterns:
            return True
        
        repo_name = os.path.basename(repo_path)
        
        for pattern in self.include_patterns:
            if fnmatch.fnmatch(repo_name, pattern):
                return True
        
        return False
    
    def should_exclude_repository(self, repo_path: str) -> bool:
        """
        检查仓库是否应该被排除
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该排除
        """
        if not self.exclude_patterns:
            return False
        
        repo_name = os.path.basename(repo_path)
        
        for pattern in self.exclude_patterns:
            if fnmatch.fnmatch(repo_name, pattern):
                return True
        
        return False
    
    def get_summary(self) -> str:
        """
        获取配置摘要
        
        Returns:
            str: 配置摘要
        """
        summary = [
            f"根目录: {self.root_directory}",
            f"包含模式: {self.include_patterns}",
            f"排除模式: {self.exclude_patterns}",
            f"详细输出: {self.verbose}",
            f"预览模式: {self.dry_run}",
            f"超时时间: {self.timeout}秒",
            f"最大线程数: {self.max_workers}",
            f"配置有效: {self.is_valid}"
        ]
        
        if self.error_message:
            summary.append(f"错误: {self.error_message}")
        
        return " | ".join(summary)
    
    def to_dict(self) -> Dict[str, Any]:
        """
        转换为字典格式
        
        Returns:
            Dict[str, Any]: 字典表示
        """
        return {
            "root_directory": self.root_directory,
            "include_patterns": self.include_patterns,
            "exclude_patterns": self.exclude_patterns,
            "verbose": self.verbose,
            "dry_run": self.dry_run,
            "timeout": self.timeout,
            "max_workers": self.max_workers,
            "is_valid": self.is_valid,
            "error_message": self.error_message
        }
    
    def __str__(self) -> str:
        """字符串表示"""
        return f"Configuration(root='{self.root_directory}', valid={self.is_valid})"
    
    def __repr__(self) -> str:
        """调试表示"""
        return self.__str__()
    
    def __eq__(self, other) -> bool:
        """相等性比较"""
        if not isinstance(other, Configuration):
            return False
        return (self.root_directory == other.root_directory and
                self.include_patterns == other.include_patterns and
                self.exclude_patterns == other.exclude_patterns and
                self.verbose == other.verbose and
                self.dry_run == other.dry_run and
                self.timeout == other.timeout and
                self.max_workers == other.max_workers)


def test_configuration():
    """测试 Configuration 类"""
    print("测试 Configuration 类...")
    
    # 测试基本配置
    config = Configuration(
        root_directory="/tmp",
        include_patterns=["*project*", "*repo*"],
        exclude_patterns=["*test*", "*temp*"],
        verbose=True,
        dry_run=False,
        timeout=300,
        max_workers=4
    )
    
    print(f"基本配置: {config.get_summary()}")
    print(f"是否有效: {config.is_valid}")
    
    # 测试仓库包含逻辑
    print(f"包含 my_project: {config.should_include_repository('/path/to/my_project')}")
    print(f"包含 test_project: {config.should_include_repository('/path/to/test_project')}")
    print(f"排除 test_project: {config.should_exclude_repository('/path/to/test_project')}")
    print(f"排除 my_project: {config.should_exclude_repository('/path/to/my_project')}")
    
    # 测试无效配置
    invalid_config = Configuration(
        root_directory="/nonexistent/path",
        include_patterns=[],
        exclude_patterns=[],
        verbose=True,
        dry_run=False,
        timeout=300,
        max_workers=4
    )
    
    print(f"无效配置: {invalid_config.get_summary()}")
    print(f"是否有效: {invalid_config.is_valid}")
    
    # 测试空配置
    empty_config = Configuration("")
    print(f"空配置: {empty_config.get_summary()}")
    print(f"是否有效: {empty_config.is_valid}")


if __name__ == "__main__":
    test_configuration()